#if defined(USE_FULL_LL_DRIVER)

#include "ll_exti.h"
#include "ll_gpio.h"
#include "stm32f4xx_ll_system.h"
#include "stdio.h"

#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || \
    defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) || defined (GPIOJ) || defined (GPIOK)

#if defined (EXTI)

#define PIN_EXTI_ZERO 0
#define PIN_EXTI_FIVE 5
#define PIN_EXTI_TEN  10
#define PIN_EXTI_SIXTEEN  16

extern Pin_ST g_pinsGroup[STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX];
// cortex-m内核外部中断线
static const uint32_t g_sysCfgExtiLineMap[] = {
    LL_SYSCFG_EXTI_LINE0,
    LL_SYSCFG_EXTI_LINE1,
    LL_SYSCFG_EXTI_LINE2,
    LL_SYSCFG_EXTI_LINE3,
    LL_SYSCFG_EXTI_LINE4,
    LL_SYSCFG_EXTI_LINE5,
    LL_SYSCFG_EXTI_LINE6,
    LL_SYSCFG_EXTI_LINE7,
    LL_SYSCFG_EXTI_LINE8,
    LL_SYSCFG_EXTI_LINE9,
    LL_SYSCFG_EXTI_LINE10,
    LL_SYSCFG_EXTI_LINE11,
    LL_SYSCFG_EXTI_LINE12,
    LL_SYSCFG_EXTI_LINE13,
    LL_SYSCFG_EXTI_LINE14,
    LL_SYSCFG_EXTI_LINE15
};


static void LL_Gpio_Exti_Handler(void)
{
    uint32_t pinIndex;
    ITStatus status = RESET;
    // 遍历所有引脚
    for (uint16_t index = 0; index < STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX; index++) {
        // 中断是否被使能
        if (g_pinsGroup[index].setup) {
            // 根据触发方式得到中断时的电平状态
            if (g_pinsGroup[index].trigger == LL_EXTI_TRIGGER_FALLING) {
                status = RESET;
            } else {
                status = SET;
            }
            // 检测是否有中断
            if (LL_EXTI_IsActiveFlag_0_31(g_pinsGroup[index].extiLine) != RESET) {
                // 清除中断标记
                LL_EXTI_ClearFlag_0_31(g_pinsGroup[index].extiLine);
                LL_mDelay(1);
                if (LL_GPIO_IsInputPinSet(g_pinsGroup[index].gpiox, g_pinsGroup[index].pinReg) == status) {
                    // 跳转到中断处理函数
                    g_pinsGroup[index].handler(g_pinsGroup[index].localPin);
                    break;
                }
            }
        }
    }
}
// 获取stm32外部中断线
uint32_t LL_GET_EXTI_LINE(uint8_t pin)
{
   return (LL_EXTI_LINE_0<<pin);
}
// 配置中断
uint32_t LL_SETUP_EXTI(LL_EXTI_InitConfig* cfg, uint16_t pin, uint16_t local, uint8_t group)
{
    // 参数检测
    if (cfg == NULL || pin<0 || pin>=STM32_GPIO_PIN_MAX || local<0 || local>=STM32_GPIO_GROUP_MAX*STM32_GPIO_PIN_MAX || group<0 || group>=STM32_GPIO_GROUP_MAX)  
    {
        printf("%s line %d error : invalid exti args...\n", __func__, __LINE__);
        return ERROR;
    }
    // 配置外部中断线
    LL_SYSCFG_SetEXTISource(group, g_sysCfgExtiLineMap[pin]);
    // 初始化外部中断
    if (LL_EXTI_Init(&cfg->initType) != SUCCESS)  
        return ERROR;
    // 记录参数到全局变量
    if (cfg->initType.LineCommand) {
        g_pinsGroup[local].setup = SET;
    } else {
        g_pinsGroup[local].setup= RESET;
    }
    g_pinsGroup[local].pin = pin;
    g_pinsGroup[local].localPin = local;
    g_pinsGroup[local].extiLine = cfg->initType.Line_0_31;
    g_pinsGroup[local].group = group;
    g_pinsGroup[local].handler = cfg->Extihandler;
    g_pinsGroup[local].trigger = cfg->initType.Trigger;
    g_pinsGroup[local].pinReg = cfg->PinReg;
    g_pinsGroup[local].gpiox = cfg->Gpiox;
    // 配置NVIC
    if (pin < PIN_EXTI_FIVE) {
		// 重定向中断向量
        NVIC_SetVector(EXTI0_IRQn + pin, (uint32_t)LL_Gpio_Exti_Handler);
		// 设置中断优先级
        NVIC_SetPriority(EXTI0_IRQn + pin, 0);
		// 使能NVIC
        NVIC_EnableIRQ(EXTI0_IRQn + pin);
    } else if (pin >= PIN_EXTI_FIVE && pin < PIN_EXTI_TEN) {
        NVIC_SetVector(EXTI9_5_IRQn, (uint32_t)LL_Gpio_Exti_Handler);
        NVIC_SetPriority(EXTI9_5_IRQn, 0);
        NVIC_EnableIRQ(EXTI9_5_IRQn);
    } else if (pin >= PIN_EXTI_TEN && pin < PIN_EXTI_SIXTEEN) {
        NVIC_SetVector(EXTI15_10_IRQn, (uint32_t)LL_Gpio_Exti_Handler);
        NVIC_SetPriority(EXTI15_10_IRQn, 0);
        NVIC_EnableIRQ(EXTI15_10_IRQn);
    }
    return SUCCESS;
}

#endif /* defined (EXTI) */
#endif
#endif /* USE_FULL_LL_DRIVER */
